"""
日志管理器模块

提供LoggerManager类用于集中管理日志记录器实例，支持：
- 单例模式确保全局统一配置
- 预设配置快速切换
- 日志记录器缓存优化性能
- 线程安全实现
"""

from .core import setup_logger
import logging
import os
import traceback

class LoggerManager:
    """
    日志记录器管理器(单例模式实现)

    功能特性:
    1. 集中管理所有日志记录器实例
    2. 提供预设配置快速切换(dev/prod/file_only)
    3. 缓存已创建的日志记录器优化性能
    4. 线程安全实现

    使用示例:
        manager = LoggerManager()
        manager.use_preset('dev')  # 使用开发环境配置
        logger = manager.get_logger('my_module')
    """
    _instance = None
    _global_base_dir = os.environ.get('GENERIC_LOGGER_BASE_DIR', 'logs')

    def __new__(cls, base_dir=None):
        try:
            if cls._instance is None:
                cls._instance = super().__new__(cls)
                cls._instance._loggers = {}
                # 优先使用参数，其次环境变量
                cls._instance._global_base_dir = base_dir if base_dir is not None else cls._global_base_dir
                cls._instance._default_config = {
                    'level': logging.INFO,
                    'handler_type': 'time',
                    'when': 'D',
                    'backup_when': 14,
                    'console': True,
                    'base_dir': cls._instance._global_base_dir
                }
            return cls._instance
        except Exception as e:
            error_msg = f"创建LoggerManager实例时发生错误: {str(e)}"
            logging.error(error_msg)
            logging.error(traceback.format_exc())
            raise RuntimeError(error_msg) from e

    @classmethod
    def set_base_dir(cls, base_dir):
        """设置全局日志基础目录"""
        try:
            cls._global_base_dir = base_dir
            if cls._instance:
                cls._instance._global_base_dir = base_dir
                cls._instance._default_config['base_dir'] = base_dir
        except Exception as e:
            error_msg = f"设置全局日志基础目录时发生错误: {str(e)}"
            logging.error(error_msg)
            logging.error(traceback.format_exc())
            raise RuntimeError(error_msg) from e

    @classmethod
    def get_base_dir(cls):
        """获取全局日志基础目录"""
        try:
            if cls._instance:
                return cls._instance._global_base_dir
            return cls._global_base_dir
        except Exception as e:
            error_msg = f"获取全局日志基础目录时发生错误: {str(e)}"
            logging.error(error_msg)
            logging.error(traceback.format_exc())
            raise RuntimeError(error_msg) from e

    PRESET_CONFIGS = {
        'dev': {
            'level': logging.DEBUG,
            'console': True,
            'show_file_line': True
        },
        'dev_file': {
            'level': logging.DEBUG,
            'console': True,
            'handler_type': 'time',
            'when': 'H',
            'backup_when': 24,
            'show_file_line': True
        },
        'prod': {
            'level': logging.INFO,
            'handler_type': 'both',
            'max_bytes': 10*1024*1024,
            'backup_count': 10,
            'when': 'midnight',
            'backup_when': 30,
            'console':False
        },
        'file_only': {
            'level': logging.INFO,
            'handler_type': 'size',
            'max_bytes': 5*1024*1024,
            'backup_count': 5,
            'console': False
        }
    }

    def use_preset(self, preset_name):
        """
        设置默认使用的预设配置

        参数:
            preset_name (str): 预设配置名称，可选值:
                - 'dev': 开发环境配置
                - 'dev_file': 开发环境带文件输出
                - 'prod': 生产环境配置
                - 'file_only': 仅文件记录

        返回:
            LoggerManager: 当前实例，支持链式调用

        示例:
            manager = LoggerManager()
            manager.use_preset('dev').get_logger('my_module')
        """
        try:
            if preset_name not in self.PRESET_CONFIGS:
                raise ValueError(f"Unknown preset: {preset_name}")

            # 更新默认配置
            self._default_config.update(self.PRESET_CONFIGS[preset_name])
            return self
        except Exception as e:
            error_msg = f"设置预设配置时发生错误: {str(e)}"
            logging.error(error_msg)
            logging.error(traceback.format_exc())
            raise RuntimeError(error_msg) from e

    def get_logger(self, name=None, config=None, preset=None, base_dir=None):
        """
        获取或创建配置好的日志记录器实例

        参数:
            name (str): 日志记录器名称，None表示获取根记录器
            config (dict): 自定义配置字典，会覆盖预设配置
            preset (str): 预设配置名称，可选值:
                - 'dev': 开发环境配置
                - 'dev_file': 开发环境带文件输出
                - 'prod': 生产环境配置
                - 'file_only': 仅文件记录
            base_dir (str): 日志文件存储的基本目录，默认为'logs'

        返回:
            logging.Logger: 配置好的日志记录器实例

        注意:
            1. 优先使用config参数，其次使用preset参数
            2. 未提供任何配置时使用默认配置
            3. 线程安全实现

        示例:
            # 使用预设配置
            logger = manager.get_logger('my_module', preset='prod')

            # 使用自定义配置
            logger = manager.get_logger(
                'custom',
                config={'level': logging.DEBUG}
            )

            # 混合使用(自定义覆盖预设)
            logger = manager.get_logger(
                'custom',
                preset='prod',
                config={'max_bytes': 20*1024*1024}
            )
        """
        try:
            # 处理预设配置
            if preset:
                if preset not in self.PRESET_CONFIGS:
                    raise ValueError(f"Unknown preset: {preset}")
                config = {**self.PRESET_CONFIGS[preset], **(config or {})}

            config = config or self._default_config.copy()

            # 如果提供了base_dir参数，覆盖配置中的base_dir
            if base_dir is not None:
                config['base_dir'] = base_dir

            cache_key = f"{name}:{str(config)}"

            if cache_key not in self._loggers:
                self._loggers[cache_key] = setup_logger(
                    module_name=name,
                    **config
                )
            return self._loggers[cache_key]
        except Exception as e:
            error_msg = f"获取日志记录器时发生错误: {str(e)}"
            logging.error(error_msg)
            logging.error(traceback.format_exc())
            raise RuntimeError(error_msg) from e